package com.fans.admin.quartz.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.fans.admin.quartz.constant.QtzConstant;
import com.fans.admin.quartz.constant.QtzConstant.ScheduleStatusEnum;
import com.fans.admin.quartz.dao.ScheduleJobMapper;
import com.fans.admin.quartz.entity.ScheduleJob;
import com.fans.admin.quartz.service.IScheduleJobService;
import com.fans.admin.quartz.util.QuartzUtil;
import com.fans.common.utils.BlankUtils;
import com.fans.common.utils.jwt.TokenUtil;

/**
 * @description: 定时任务表服务实现类
 * @date: 2020年01月14 16:55:11
 * @author: fanhaohao
 * @version: 1.0
 */
@Service
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper,ScheduleJob> implements IScheduleJobService {

	@Autowired
    private ScheduleJobMapper scheduleJobMapper;

	@Autowired
	private Scheduler scheduler;
    
	/**
	 * @Title：list  
	 * @Description: 定时任务表分页查询
	 * @author: fanhaohao
	 * @date 2020年01月14 16:55:11
	 * @param @param page
	 * @param @param map
	 * @param @return 
	 * @return List<Map<String,Object>> 
	 * @throws
	 */
	@Override
	public List<Map<String, Object>> list(Page<ScheduleJob> page,Map<String, Object> map){
		return scheduleJobMapper.list(page,map);
	}
	
	/**
	 * @Title：deleteBatchByIdLogic  
	 * @Description: 定时任务表根据id逻辑删除
	 * @author: fanhaohao
	 * @date 2020年01月14 16:55:11
	 * @param @param id 
	 * @return void 
	 * @throws
	 */
	@Override
	public void deleteBatchByIdLogic(Object id){
		ScheduleJob scheduleJob = new ScheduleJob();
		scheduleJob.setId(String.valueOf(id));
		scheduleJob.preUpdate();
		scheduleJob.setUpdateBy(TokenUtil.getUserId());
		scheduleJob.setDelFlag("1");
		this.updateById(scheduleJob);
	}
	
	/**
	 * @Title：deleteBatchByIdsLogic    
	 * @Description: 定时任务表逻辑批量删除
	 * @author: fanhaohao
	 * @date 2020年01月14 16:55:11
	 * @param @param ids 
	 * @return void 
	 * @throws
	 */
	@Override
	public void deleteBatchByIdsLogic(List<String> ids) {
		List<ScheduleJob> list = new ArrayList<>();
		for (String id : ids) {
			ScheduleJob scheduleJob = new ScheduleJob();
			scheduleJob.setId(String.valueOf(id));
			scheduleJob.preUpdate();
			scheduleJob.setUpdateBy(TokenUtil.getUserId());
			scheduleJob.setDelFlag("1");
			list.add(scheduleJob);
		}
		this.updateBatchById(list);
	}

	/**
	 * @Title：findList 
	 * @Description: 查询
	 * @author: fanhaohao
	 * @date 2020年1月10日 上午9:02:05 
	 * @param @return 
	 * @return List<ScheduleJob> 
	 * @throws
	 */
	@Override
	public List<ScheduleJob> findList(ScheduleJob scheduleJob) {
		EntityWrapper<ScheduleJob> wrapper = new EntityWrapper<ScheduleJob>();
		wrapper.eq("del_flag", "0");
		return super.selectList(wrapper);
	}

	/**
	 * @Title：listByIds  
	 * @Description: 根据id list集合来查询
	 * @author: fanhaohao
	 * @date 2020年1月15日 上午9:23:04 
	 * @param @param idArr
	 * @param @return 
	 * @return List<ScheduleJob> 
	 * @throws
	 */
	@Override
	public List<ScheduleJob> listByIds(List<String> scheduleJobIds) {
		return scheduleJobMapper.listByIds(scheduleJobIds);
	}
	
/**===========================================业务操作====================================================**/
  	
	
	/**
	 * 判断是否存在任务
	 * 
	 * @param scheduler
	 * @param jobId
	 * @return
	 */
	@Override
	public Boolean isExistScheduler(Scheduler scheduler, String jobId) {
		return QuartzUtil.isExistScheduler(scheduler, jobId);
	}
	
	/**
	 * 修改状态
	 * 
	 * @param scheduleJobIds
	 * @param status
	 */
	@Override
	public void updateStatus(List<String> scheduleJobIds, String status) throws SchedulerException {

		List<ScheduleJob> jobs = this.listByIds(scheduleJobIds);
		if (BlankUtils.isNotBlank(jobs)) {
			String msg = "";
			for (ScheduleJob scheduleJob : jobs) {
				if (ScheduleStatusEnum.DISABLE.getCode().equals(status)
						|| ScheduleStatusEnum.DELETE.getCode().equals(status)) {
					if (QuartzUtil.isExistScheduler(scheduler, scheduleJob.getId())) {
						msg += "，"  + scheduleJob.getJobName();
					}
				}
			}
			if (BlankUtils.isNotBlank(msg)) {
				throw new SchedulerException("任务【" + msg.substring(1) + "】正在运行中，请先删除这些任务的执行信息，才能进行操作！");
			} else {
				for (ScheduleJob scheduleJob : jobs) {
					scheduleJob.setJobStatus(status);
				}
				this.updateBatchById(jobs);
			}
		} else {
			throw new SchedulerException("没有找到相关定时任务信息！");
		}
	}

	/**
	 * 添加或者修改任务信息
	 * @param jobGroup
	 * @param jobName
	 * @param cronExpression
	 * @param isStartJob 是否启动任务
	 * @return
	 */
	@Override
	public ScheduleJob createOrUpdate(HttpServletRequest request, ScheduleJob scheduleJob) throws Exception {
		String jobId = scheduleJob.getId();
		if (BlankUtils.isBlank(jobId)) {
			scheduleJob.preInsert();
			scheduleJob.setJobStatus("1");// 设置成启用状态
			scheduleJob.setCreateBy(TokenUtil.getUserId());
		} else{
			scheduleJob.preUpdate();
			scheduleJob.setUpdateBy(TokenUtil.getUserId());
		}
		scheduleJob.setCronExpression(scheduleJob.getCronExpression());
		scheduleJob.setRemarks(scheduleJob.getRemarks());
		this.insertOrUpdate(scheduleJob);
		
		//如果任务存在，则修改表达式；否则，启动任务
		if (QuartzUtil.isExistScheduler(scheduler, scheduleJob.getId())) {
			QuartzUtil.rescheduleScheduleJob(scheduler, scheduleJob);
		} else {
			QuartzUtil.createScheduleJob(scheduler, scheduleJob, false);
		}
		
		return scheduleJob;
	}

	/**
	 * 计划任务信息列表
	 */
	@Override
	public List<ScheduleJob> planScheduleListJson() throws SchedulerException {
		return QuartzUtil.getPlanScheduleJob(scheduler);
	}

	/**
	 * 运行中任务信息列表
	 */
	@Override
	public List<ScheduleJob> runningScheduleListJson() throws SchedulerException {
		return QuartzUtil.getRunningScheduleJob(scheduler);
	}

	/**
	 * 创建任务
	 */
	@Override
	public void createScheduleJob(List<String> scheduleJobIds) throws SchedulerException {
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);

		for (ScheduleJob scheduleJob : scheduleJobs) {
			QuartzUtil.createScheduleJob(scheduler, scheduleJob, false);
		}
	}
	

	private List<ScheduleJob> getCheckScheduleJobList(List<String> scheduleJobIds) throws SchedulerException {
		List<ScheduleJob> jobs = this.listByIds(scheduleJobIds);
		if (BlankUtils.isNotBlank(jobs)) {
			String key = "";
			for (ScheduleJob scheduleJob : jobs) {
				key = "【" + scheduleJob.getJobName() + "】";
				if (ScheduleStatusEnum.DISABLE.getCode().equals(scheduleJob.getJobStatus())) {
					throw new SchedulerException(key + "定时器是禁用状态，不允许操作，请先启用！");
				} else if (ScheduleStatusEnum.DELETE.getCode().equals(scheduleJob.getJobStatus())) {
					throw new SchedulerException(key + "定时器是删除状态，不允许操作！");
				} else {
					break;
				}
			}
		} else {
			throw new SchedulerException("没有找到相关定时任务信息！");
		}
		return jobs;
	}

	/**
	 * 暂停任务
	 */
	@Override
	public void pauseScheduleJob(List<String> scheduleJobIds) throws SchedulerException {
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);

		for (ScheduleJob scheduleJob : scheduleJobs) {
			QuartzUtil.pauseScheduleJob(scheduler, scheduleJob);
			scheduleJob.setStatus(QtzConstant.ScheduleStatus.PAUSE.getValue());
		}
		super.updateBatchById(scheduleJobs);
	}

	/**
	 * 恢复任务
	 */
	@Override
	public void resumeScheduleJob(List<String> scheduleJobIds) throws SchedulerException {
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);

		for (ScheduleJob scheduleJob : scheduleJobs) {
			QuartzUtil.resumeScheduleJob(scheduler, scheduleJob);
			scheduleJob.setStatus(QtzConstant.ScheduleStatus.NORMAL.getValue());
		}
		super.updateBatchById(scheduleJobs);
	}

	/**
	 * 删除任务
	 */
	@Override
	public void deleteScheduleJob(List<String> scheduleJobIds) throws SchedulerException {
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);

		for (ScheduleJob scheduleJob : scheduleJobs) {
			QuartzUtil.deleteScheduleJob(scheduler, scheduleJob);
		}
		this.deleteBatchByIdsLogic(scheduleJobIds);
	}
	/**
	 * 立即运行任务
	 */
	@Override
	public void triggerScheduleJob(List<String> scheduleJobIds)
			throws SchedulerException {
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);
		
		for (ScheduleJob scheduleJob : scheduleJobs) {
			scheduleJob.setStatus(QtzConstant.ScheduleStatus.NORMAL.getValue());
			super.updateById(scheduleJob);
			QuartzUtil.triggerScheduleJob(scheduler, scheduleJob);
		}
	}
	
	/**
	 * 修改表达式
	 * @param scheduleJobId
	 * @throws SchedulerException
	 */
	@Override
	public void rescheduleScheduleJob(HttpServletRequest request, List<String> scheduleJobIds, String cronExpression)
			throws SchedulerException {
		QuartzUtil.checkCronExpression(cronExpression);
		
		List<ScheduleJob> scheduleJobs = getCheckScheduleJobList(scheduleJobIds);
		
		for (ScheduleJob scheduleJob : scheduleJobs) {
			scheduleJob.setCronExpression(cronExpression);
			scheduleJob.preUpdate();
			scheduleJob.setUpdateBy(TokenUtil.getUserId());
			scheduleJob.setDelFlag("0");
			QuartzUtil.rescheduleScheduleJob(scheduler, scheduleJob);
		}
		this.updateBatchById(scheduleJobs);
	}
	
	/**
	 * 通过表达式计算时间结果
	 * @param cronExpression
	 * @throws SchedulerException
	 */
	@Override
	public Date getCronExpressionResult(Date startTime, String cronExpression)
			throws SchedulerException {
		return QuartzUtil.getCronExpressionResult(startTime, cronExpression);
	}

	
}
